package com.gitee.wsl.android.ui.theme.inject

import android.R
import android.annotation.SuppressLint
import android.app.Activity
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.CheckBox
import android.widget.CheckedTextView
import android.widget.EditText
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.RadioButton
import android.widget.SeekBar
import android.widget.Switch
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.WindowInsetsControllerCompat
import com.gitee.wsl.android.ext.base.adjustOpacity
import com.gitee.wsl.android.ext.base.buildColorStateList
import com.gitee.wsl.android.ext.base.isDarkColor
import com.gitee.wsl.common.ui.theme.ColorPaletteScheme
import com.gitee.wsl.common.ui.theme.Theme
import com.gitee.wsl.common.ui.theme.TypographyScheme
import com.gitee.wsl.ext.base.ColorExt
import com.gitee.wsl.ext.base.ColorExt.ON_SURFACE_OPACITY_BUTTON_DISABLED
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.navigation.NavigationView

object AndroidViewThemeInject {
    fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> injectTheme(theme:THEME, view: View):Boolean{
        when(view){
            is BottomNavigationView-> view.theme(theme)
            is NavigationView -> view.theme(theme)
            is MenuItem -> (view as MenuItem).theme(theme)
            is SeekBar -> view.theme(theme)
            is ProgressBar -> view.theme(theme)
            is ImageButton -> view.theme(theme)
            is ImageView -> view.theme(theme)
            is CheckedTextView -> view.theme(theme)
            is CheckBox -> view.theme(theme)
            is RadioButton -> view.theme(theme)
            is EditText -> view.theme(theme)
            is Switch -> view.theme(theme)
            is Button -> view.theme(theme)
            is TextView -> view.theme(theme)
            else-> return false
        }
        return true
    }
}

inline fun <reified T,K> useTheme(view:T,theme:K, config:T.(scheme:K)->Unit){
    config(view,theme)
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> View.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        setBackgroundColor(scheme.background)
    }
}

@JvmOverloads
fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> BottomNavigationView.theme(theme:THEME){
    useTheme(this,theme.colorScheme.toAndroid()){scheme->
        setBackgroundColor(scheme.surface)

        itemIconTintList =ColorExt. buildColorStateList(
            R.attr.state_checked to scheme.onSecondaryContainer,
            -R.attr.state_checked to scheme.onSurfaceVariant
        )

        itemTextColor = ColorExt.buildColorStateList(
            R.attr.state_checked to scheme.onSurface,
            -R.attr.state_checked to scheme.onSurfaceVariant
        )

       itemActiveIndicatorColor = ColorStateList.valueOf(scheme.secondaryContainer)
    }
}

@JvmOverloads
fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> NavigationView.theme(theme:THEME, colorIcons: Boolean = true) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        if (itemBackground != null) {
            itemBackground!!.setTintList(
                ColorExt.buildColorStateList(
                    R.attr.state_checked to scheme.secondaryContainer,
                    -R.attr.state_checked to Color.TRANSPARENT
                )
            )
        }
        background.setTintList(ColorStateList.valueOf(scheme.surface))

        val colorStateList =ColorExt.buildColorStateList(
            R.attr.state_checked to scheme.onSecondaryContainer,
            -R.attr.state_checked to scheme.onSurfaceVariant
        )

        itemTextColor = colorStateList
        if (colorIcons) {
            itemIconTintList = colorStateList
        }
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> MenuItem.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        colorMenuItemIcon(scheme.onSurfaceVariant, this)
        colorMenuItemText(scheme.onSurface, this)
    }
}

private fun colorMenuItemIcon(@ColorInt color: Int, item: MenuItem) {
    item.icon?.setTint(color)
}

private fun colorMenuItemText(@ColorInt color: Int, item: MenuItem) {
    val newItemTitle = SpannableString(item.title)
    newItemTitle.setSpan(
        ForegroundColorSpan(color),
        0,
        newItemTitle.length,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    )
    item.title = newItemTitle
}

/**
 * Public for edge cases. For most cases use [tintDrawable] instead
 */
fun colorDrawable(drawable: Drawable, @ColorInt color: Int): Drawable {
    val wrap = DrawableCompat.wrap(drawable)
    wrap.colorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(
        color,
        BlendModeCompat.SRC_ATOP
    )
    return wrap
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> ActionBarDrawerToggle.theme(theme:THEME, drawable: Drawable) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        val wrap = DrawableCompat.wrap(drawable)
        wrap.setColorFilter(scheme.onSurface, PorterDuff.Mode.SRC_ATOP)
        setHomeAsUpIndicator(wrap)
        drawerArrowDrawable.color = scheme.onSurface
    }
}

/**
 * Public for special cases, e.g. action mode. You probably want [themeStatusBar] for most cases instead.
 */
fun colorStatusBar(activity: Activity, @ColorInt color: Int) {
    val window = activity.window ?: return
    val isLightBackground = !ColorExt.isDarkColor(color)
    val decor = window.decorView
    window.statusBarColor = color
    window.navigationBarColor = color
    WindowInsetsControllerCompat(window, decor).isAppearanceLightStatusBars = isLightBackground
    WindowInsetsControllerCompat(window, decor).isAppearanceLightNavigationBars = isLightBackground
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> Activity.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        colorStatusBar(this,scheme.surface)
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> SeekBar.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        themeHorizontalProgressBar(this, scheme.primary)
        thumb.setColorFilter(scheme.primary, PorterDuff.Mode.SRC_IN)
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> ProgressBar.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        themeHorizontalProgressBar(this, scheme.primary)
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> ProgressBar.themeCircular(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        indeterminateDrawable.setColorFilter(scheme.primary, PorterDuff.Mode.SRC_ATOP)
    }
}

fun themeHorizontalProgressBar(progressBar: ProgressBar?, @ColorInt color: Int) {
    progressBar?.indeterminateDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
    progressBar?.progressDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> TextView.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        setTextColor(scheme.primary)
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> ImageView.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        imageTintList = ColorStateList.valueOf(scheme.onPrimaryContainer)
        backgroundTintList = ColorStateList.valueOf(scheme.primaryContainer)
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> ImageButton.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        imageTintList = ColorExt.buildColorStateList(
            R.attr.state_selected to scheme.primary,
            -R.attr.state_selected to scheme.onSurfaceVariant,
            R.attr.state_enabled to scheme.onSurfaceVariant,
            -R.attr.state_enabled to ColorExt.adjustOpacity(
                scheme.onSurface,
                ON_SURFACE_OPACITY_BUTTON_DISABLED
            )
        )
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> Button.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        setTextColor(
            ColorExt.buildColorStateList(
                R.attr.state_enabled to scheme.primary,
                -R.attr.state_enabled to ColorExt.adjustOpacity(
                    scheme.onSurface,
                    ON_SURFACE_OPACITY_BUTTON_DISABLED
                )
            )
        )
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> CheckedTextView.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        checkMarkTintList =  ColorExt.buildColorStateList(
            -R.attr.state_checked to Color.GRAY,
            -R.attr.state_enabled to Color.GRAY,
            R.attr.state_checked to scheme.primary
        )
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> CheckBox.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        buttonTintList = ColorExt. buildColorStateList(
            -R.attr.state_checked to Color.GRAY,
            -R.attr.state_enabled to Color.GRAY,
            R.attr.state_checked to scheme.primary
        )
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> RadioButton.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        buttonTintList = ColorExt. buildColorStateList(
            -R.attr.state_checked to Color.GRAY,
            R.attr.state_checked to scheme.primary
        )
    }
}

fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> EditText.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->
        backgroundTintList =ColorExt. buildColorStateList(
            -R.attr.state_focused to scheme.outline,
            R.attr.state_focused to scheme.primary
        )

        setHintTextColor(scheme.onSurfaceVariant)
        setTextColor(scheme.onSurface)
    }
}

const val SWITCH_COMPAT_TRACK_ALPHA = 77

@SuppressLint("UseSwitchCompatOrMaterialCode")
fun <P: ColorPaletteScheme,T: TypographyScheme,THEME: Theme<P,T>> Switch.theme(theme:THEME) {
    useTheme(this, theme.colorScheme.toAndroid()) { scheme ->

        val trackColor1 = Color.argb(
            SWITCH_COMPAT_TRACK_ALPHA,
            Color.red(scheme.primary),
            Color.green(scheme.primary),
            Color.blue(scheme.primary)
        )
        val thumbUncheckedColor = 0xececec
        val trackUncheckedColor = 0xb2b2b2

        val thumbColor = ColorStateList(
            arrayOf(intArrayOf(R.attr.state_checked), intArrayOf()),
            intArrayOf(scheme.primary, thumbUncheckedColor)
        )
        val trackColor = ColorStateList(
            arrayOf(intArrayOf(R.attr.state_checked), intArrayOf()),
            intArrayOf(trackColor1, trackUncheckedColor)
        )
        DrawableCompat.setTintList(thumbDrawable,thumbColor)
        DrawableCompat.setTintList(trackDrawable, trackColor)
    }
}

fun getColoredSpan(title: String, color: Int): Spannable {
    val text: Spannable = SpannableString(title)
    text.setSpan(
        ForegroundColorSpan(color),
        0,
        text.length,
        Spannable.SPAN_INCLUSIVE_INCLUSIVE
    )
    return text
}